package cn.iocoder.yudao.module.digital.service.cardkeythirdpartyapirecord;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import cn.iocoder.yudao.framework.common.util.json.JsonUtils;
import cn.iocoder.yudao.module.digital.enums.cardkeysecret.CardKeyApiRequestTypeEnum;
import cn.iocoder.yudao.module.digital.service.cardchannel.constant.CardKeyThirdPartyApiConstant;
import cn.iocoder.yudao.module.digital.service.cardchannel.model.EGiftErrorResponse;
import cn.iocoder.yudao.module.digital.service.cardchannel.model.ListByFailedHttpCodeVO;
import cn.iocoder.yudao.module.digital.service.cardchannel.model.ListByHttpStatusCodesVO;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import jodd.util.StringUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;

import org.springframework.validation.annotation.Validated;

import java.util.*;

import cn.iocoder.yudao.module.digital.controller.admin.cardkeythirdpartyapirecord.vo.*;
import cn.iocoder.yudao.module.digital.dal.dataobject.cardkeythirdpartyapirecord.CardkeyThirdPartyApiRecordDO;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;

import cn.iocoder.yudao.module.digital.dal.mysql.cardkeythirdpartyapirecord.CardkeyThirdPartyApiRecordMapper;

import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.yudao.module.digital.enums.ErrorCodeConstants.*;

/**
 * 卡密第三方API请求记录 Service 实现类
 *
 * @author 超管
 */
@Service
@Validated
@Slf4j
public class CardkeyThirdPartyApiRecordServiceImpl implements CardkeyThirdPartyApiRecordService {

    @Resource
    private CardkeyThirdPartyApiRecordMapper cardkeyThirdPartyApiRecordMapper;

    @Override
    public Long createCardkeyThirdPartyApiRecord(CardkeyThirdPartyApiRecordSaveReqVO createReqVO) {
        // 插入
        CardkeyThirdPartyApiRecordDO cardkeyThirdPartyApiRecord = BeanUtils.toBean(createReqVO, CardkeyThirdPartyApiRecordDO.class);
        cardkeyThirdPartyApiRecordMapper.insert(cardkeyThirdPartyApiRecord);
        // 返回
        return cardkeyThirdPartyApiRecord.getId();
    }

    @Override
    public void updateCardkeyThirdPartyApiRecord(CardkeyThirdPartyApiRecordSaveReqVO updateReqVO) {
        // 校验存在
        validateCardkeyThirdPartyApiRecordExists(updateReqVO.getId());
        // 更新
        CardkeyThirdPartyApiRecordDO updateObj = BeanUtils.toBean(updateReqVO, CardkeyThirdPartyApiRecordDO.class);
        cardkeyThirdPartyApiRecordMapper.updateById(updateObj);
    }

    @Override
    public void deleteCardkeyThirdPartyApiRecord(Long id) {
        // 校验存在
        validateCardkeyThirdPartyApiRecordExists(id);
        // 删除
        cardkeyThirdPartyApiRecordMapper.deleteById(id);
    }

    private void validateCardkeyThirdPartyApiRecordExists(Long id) {
        if (cardkeyThirdPartyApiRecordMapper.selectById(id) == null) {
            throw exception(CARDKEY_THIRD_PARTY_API_RECORD_NOT_EXISTS);
        }
    }

    @Override
    public CardkeyThirdPartyApiRecordDO getCardkeyThirdPartyApiRecord(Long id) {
        return cardkeyThirdPartyApiRecordMapper.selectById(id);
    }

    @Override
    public PageResult<CardkeyThirdPartyApiRecordDO> getCardkeyThirdPartyApiRecordPage(CardkeyThirdPartyApiRecordPageReqVO pageReqVO) {
        return cardkeyThirdPartyApiRecordMapper.selectPage(pageReqVO);
    }

    @Override
    public int updateById(CardkeyThirdPartyApiRecordDO apiRecordDO) {
        return cardkeyThirdPartyApiRecordMapper.updateById(apiRecordDO);
    }

    @Override
    public CardkeyThirdPartyApiRecordDO getCardkeyThirdPartyApiRecordByRequestIdAndType(CardKeyApiRequestTypeEnum requestType, String requestId) {
        final LambdaQueryWrapper<CardkeyThirdPartyApiRecordDO> wrapper = Wrappers.lambdaQuery();
        return cardkeyThirdPartyApiRecordMapper.selectOne(wrapper.eq(CardkeyThirdPartyApiRecordDO::getRequestId, requestId).eq(CardkeyThirdPartyApiRecordDO::getRequestType, requestType.getValue()));
    }

    @Override
    public PageResult<CardkeyThirdPartyApiRecordDO> listByHttpStatusCodesNotRevert(ListByHttpStatusCodesVO vo) {
        return cardkeyThirdPartyApiRecordMapper.listByHttpStatusCodesNotRevert(vo);
    }

    @Override
    public PageResult<CardkeyThirdPartyApiRecordDO> listByFailedHttpCodeNotRevert(ListByFailedHttpCodeVO vo) {
        return cardkeyThirdPartyApiRecordMapper.listByFailedHttpCodeNotRevert(vo);
    }

    //

    // 创建api请求记录
    @Override
    public Long createApiRecord(CardKeyApiRequestTypeEnum requestType, String orderNo, String productNo, String currencyCode, Integer denomination,
                                String requestId, String url, String requestBody, Map<String, String> requestHeaders,
                                String generateEGiftRequestId) {
        final CardkeyThirdPartyApiRecordDO recordDO = getCardkeyThirdPartyApiRecordByRequestIdAndType(requestType, requestId);
        if (recordDO != null) {
            return recordDO.getId();
        }

        final CardkeyThirdPartyApiRecordSaveReqVO vo = new CardkeyThirdPartyApiRecordSaveReqVO();
        vo.setReverse(false);
        vo.setProductNo(productNo);
        vo.setDenomination(denomination);
        vo.setCurrencyCode(currencyCode);
        vo.setRequestType(requestType.getValue());
        vo.setRequestId(requestId);
        vo.setGenerateEGiftRequestId(generateEGiftRequestId);
        vo.setOrderNo(orderNo);
        vo.setHttpStatusCode(CardKeyThirdPartyApiConstant.HTTP_STATUS_CODE_DEFAULT);
        vo.setRequestUrl(url);
        if (CollUtil.isNotEmpty(requestHeaders)) {
            vo.setRequestHeaders(JsonUtils.toJsonString(requestHeaders));
        }
        if (StringUtil.isNotEmpty(requestBody)) {
            vo.setRequestBody(requestBody);
        }

        final Long apiRecordId = createCardkeyThirdPartyApiRecord(vo);
        log.info("领取卡密-创建api请求记录, orderNo = {}, requestId = {}, apiRecordId = {}",
                orderNo, requestId, apiRecordId);
        return apiRecordId;
    }

    // 更新api请求记录
    @Override
    public void updateApiRecordWithRequestBody(Long apiRecordId, String requestBody) {
        final CardkeyThirdPartyApiRecordDO apiRecordDO = new CardkeyThirdPartyApiRecordDO();
        apiRecordDO.setId(apiRecordId);
        apiRecordDO.setRequestBody(requestBody);
        updateById(apiRecordDO);
    }


    // 更新api请求记录-成功
    @Override
    public void updateApiRecordWithSuccessResponse(Long apiRecordId, String responseBody) {
        final CardkeyThirdPartyApiRecordDO apiRecordDO = new CardkeyThirdPartyApiRecordDO();
        apiRecordDO.setId(apiRecordId);
        apiRecordDO.setHttpStatusCode(CardKeyThirdPartyApiConstant.HTTP_STATUS_CODE_SUCCESS);
        apiRecordDO.setResponseBody(responseBody);
        apiRecordDO.setErrorCode("");
        apiRecordDO.setErrorDesc("");
        updateById(apiRecordDO);
    }

    // 更新api请求记录-失败
    @Override
    public void updateApiRecordWithErrorResponse(Long apiRecordId, int httpStatusCode, String responseBody, EGiftErrorResponse errorResponse) {
        final CardkeyThirdPartyApiRecordDO apiRecordDO = new CardkeyThirdPartyApiRecordDO();
        apiRecordDO.setId(apiRecordId);
        apiRecordDO.setHttpStatusCode(httpStatusCode);
        if (errorResponse != null) {
            apiRecordDO.setErrorCode(errorResponse.getErrorCode());
            apiRecordDO.setErrorDesc(errorResponse.getMessage());
        } else {
            apiRecordDO.setErrorCode("");
            apiRecordDO.setErrorDesc("");
        }
        if (StrUtil.isNotEmpty(responseBody)) {
            apiRecordDO.setResponseBody(responseBody);
        } else {
            apiRecordDO.setResponseBody("");
        }
        updateById(apiRecordDO);
    }

    // 更新状态为已撤销
    @Override
    public void updateApiRecordToReverseSuccess(Long apiRecordId) {
        final CardkeyThirdPartyApiRecordDO apiRecordDO = new CardkeyThirdPartyApiRecordDO();
        apiRecordDO.setId(apiRecordId);
        apiRecordDO.setReverse(true);
        updateById(apiRecordDO);
    }

}